import urllib.parse
from datetime import datetime, timedelta
import httpx
from providers.base_provider import BaseProvider
from models.m import DingtalkUser, User
from tortoise.exceptions import DoesNotExist

class DingtalkProvider(BaseProvider):
    """钉钉登录提供者"""
    
    async def get_authorization_url(self) -> str:
        """获取钉钉授权URL"""
        params = {
            "client_id": self.config["client_id"],
            "response_type": "code",
            "scope": "openid",
            "redirect_uri": self.config["redirect_uri"],
            "prompt": "consent"
        }
        
        authorize_url = self.config["authorize_url"]
        query_string = urllib.parse.urlencode(params)
        return f"{authorize_url}?{query_string}"
    
    async def exchange_code_for_token(self, code: str) -> dict:
        """用授权码换取访问令牌"""
        token_url = self.config["token_url"]
        
        payload = {
            "clientId": self.config["client_id"],
            "clientSecret": self.config["client_secret"],
            "code": code,
            "grantType": "authorization_code"
        }
        
        headers = {
            "Content-Type": "application/json",
            "Accept": "application/json"
        }
        
        try:
            async with httpx.AsyncClient() as client:
                response = await client.post(token_url, json=payload, headers=headers, timeout=10.0)
                return {
                    "status_code": response.status_code,
                    "data": response.json() if response.content else {},
                    "text": response.text
                }
        except Exception as e:
            return {
                "status_code": 500,
                "data": {},
                "text": f"请求异常: {str(e)}"
            }
    
    async def get_user_info(self, access_token: str) -> dict:
        """获取钉钉用户信息"""
        userinfo_url = self.config["userinfo_url"]
        
        headers = {
            "x-acs-dingtalk-access-token": access_token
        }
        
        try:
            async with httpx.AsyncClient() as client:
                response = await client.get(userinfo_url, headers=headers, timeout=10.0)
                return response.json()
        except Exception as e:
            return {"error": f"获取用户信息异常: {str(e)}"}
    
    async def save_user_info(self, user_info: dict, token_info: dict) -> User:
        """保存钉钉用户信息到数据库"""
        try:
            # 尝试查找现有的钉钉用户
            dingtalk_user = await DingtalkUser.get(unionid=user_info["unionId"])
            # 更新现有用户信息
            dingtalk_user.openid = user_info.get("openId", "")
            dingtalk_user.nickname = user_info.get("nick", "")
            dingtalk_user.avatar_url = user_info.get("avatarUrl", "")
            dingtalk_user.access_token = token_info.get("accessToken", "")
            dingtalk_user.refresh_token = token_info.get("refreshToken", "")
            dingtalk_user.expire_at = datetime.utcnow() + timedelta(seconds=token_info.get("expireIn", 7200))
            dingtalk_user.updated_at = datetime.utcnow()
            await dingtalk_user.save()
        except DoesNotExist:
            # 创建新的钉钉用户
            dingtalk_user = await DingtalkUser.create(
                unionid=user_info["unionId"],
                openid=user_info.get("openId", ""),
                nickname=user_info.get("nick", ""),
                avatar_url=user_info.get("avatarUrl", ""),
                access_token=token_info.get("accessToken", ""),
                refresh_token=token_info.get("refreshToken", ""),
                expire_at=datetime.utcnow() + timedelta(seconds=token_info.get("expireIn", 7200))
            )
        
        # 这里可以关联或创建本地用户
        # 简化处理，直接返回钉钉用户关联的本地用户
        return dingtalk_user